/**
 * @file hscuda_rasterdata.h
 * @author iam002
 * @brief cuda版本RasterData模板类
 * @version 1.0
 * @date 2024-10-15
 * 
 * @copyright Copyright (c) 2024
 * 
 */
#ifndef __HSCUDA_RASTERDATA_H__
#define __HSCUDA_RASTERDATA_H__

#include "hscuda_rasterview.h"
#include "hs_rasterdata.h"

namespace hscuda
{

namespace raster
{

/**
 * @brief cuda版本的RasterData模板类
 * @note cuda类的数据均按行优先进行存储
 * @tparam DataType 
 */
template<typename DataType>
class RasterData
{

public:

    /**
     * @brief 默认构造函数
     * 
     */
    RasterData();


    /**
     * @brief 构造函数
     * 
     * @param size_x 图宽, x方向指水平方向
     * @param size_y 图高, y方向指竖直方向
     */
    RasterData(int size_x, int size_y);


    /**
     * @brief 析构函数
     * 
     */
    ~RasterData();


    /**
     * @brief 拷贝构造函数, 输入对象交出所有权
     * 
     * @param obj RasterData输入对象
     */
    RasterData(RasterData & obj);


    /**
     * @brief 移动构造函数, 输入对象交出所有权
     * 
     * @param obj RasterData输入对象
     */
    RasterData(RasterData && obj);


    /**
     * @brief 赋值构造函数, 输入对象交出所有权
     * 
     * @param obj RasterData输入对象
     * @return RasterData& 新RasterData对象
     */
    RasterData & operator=(RasterData & obj);


    /**
     * @brief 赋值移动构造函数, 输入对象交出所有权
     * 
     * @param obj RasterData输入对象
     * @return RasterData& 新RasterData对象
     */
    RasterData & operator=(RasterData && obj);

    /**
     * @brief 初始化RasterData, 此函数会重新分配内存
     * 
     * @param size_x 图宽, x方向指水平方向
     * @param size_y 图高, y方向指竖直方向
     */
    void init(int size_x, int size_y);


    /**
     * @brief 释放分配的数据内存, 并清空RasterView
     * 
     */
    void release();


    /**
     * @brief 拷贝RasterData对象(重新分配内存)
     * 
     * @param obj 拷贝源
     */
    void copyFrom(const RasterData & obj);


    /**
     * @brief 返回 RasterView 对象
     * 
     * @return RasterView<DataType>& 
     */
    RasterView<DataType> & view()
    {
        return m_view;
    }


    /**
     * @brief 返回 RasterView 对象
     * 
     * @return RasterView<DataType>& 
     */
    const RasterView<DataType> & view() const
    {
        return m_view;
    }


    /**
     * @brief 将数据复制到主机端
     * 
     * @param obj 
     * @return true 
     * @return false 
     */
    bool toHost(hs::raster::RasterData<DataType> & obj);

protected:

    /// @brief 原始数据指针
    DataType* m_p_rawdata;

    /// @brief 实际分配内存大小
    int m_alloc_size;

    /// @brief RasterView类
    RasterView<DataType> m_view;

private:
    /* 限定 DataType 必须为 float 或者 double */
    typename std::enable_if<std::is_same<DataType, double>::value || std::is_same<DataType, float>::value, void>::type _type_check() {}

};


/**
 * @brief 将主机上的栅格数据拷贝到GPU设备上
 * 
 * @tparam DataType 数据类型
 * @param host_view 输入, 主机端数据
 * @param raster 输出, 设备端数据
 * @return true 
 * @return false 
 */
template<typename DataType>
bool host2device(const hs::raster::RasterView<DataType> & host_view, hscuda::raster::RasterData<DataType> & raster);


/**
 * @brief 将GPU设备上的栅格数据拷贝到主机上
 * 
 * @tparam DataType 数据类型
 * @param device_view 输入, 设备端数据
 * @param raster 输出, 主机端数据
 * @return true 
 * @return false 
 */
template<typename DataType>
bool device2host(const hscuda::raster::RasterView<DataType> & device_view, hs::raster::RasterData<DataType> & raster);


} // end namespace raster

} // end namespace hscuda

#endif
